import os
import logging

from PyQt5 import QtWidgets, QtGui, QtCore

logger = logging.getLogger(__name__)

class PliantQTextBrowser(QtWidgets.QTextBrowser):
    
    def __init__(self, main_window, parent=None):
        super(PliantQTextBrowser, self).__init__(parent)
        self.parent = parent
        self.main_window = main_window
        
        self.common_functions = PliantWidgetsCommonFunctions(
            self, self.main_window)

        # self.verticalScrollBar().sliderMoved.connect(
        #     self.record_position)
        self.mousePosition = None
        self.ignore_wheel_event = False
        self.ignore_wheel_event_number = 0

        self.at_end = False
        self.page_cursors = []
        self.page_number = 0

    def generate_textbrowser_context_menu(self, position):
        selection = self.textCursor().selection()
        selection = selection.toPlainText()

        # current_chapter = self.parent.metadata['position']['current_chapter']
        cursor_at_mouse = self.cursorForPosition(position)
        annotation_is_present = self.common_functions.annotation_specific(
            'check', 'text', current_chapter, cursor_at_mouse.position())

        contextMenu = QtWidgets.QMenu()

        # The following cannot be None because a click
        # outside the menu means that the action variable is None.
        defineAction = fsToggleAction = dfToggleAction = 'Caesar si viveret, ad remum dareris'
        searchWikipediaAction = searchYoutubeAction = 'Does anyone know something funny in Latin?'
        searchAction = searchGoogleAction = bookmarksToggleAction = 'TODO Insert Latin Joke'
        deleteAnnotationAction = editAnnotationNoteAction = 'Latin quote 2. Electric Boogaloo.'
        flowModeAction = singlePageAction = doublePageAction = 'We know the rules, you and I'
        annotationActions = []

        view_submenu_string = self._translate('PliantQTextBrowser', 'View')
        viewSubMenu = contextMenu.addMenu(view_submenu_string)
        viewSubMenu.setIcon(
            self.main_window.QImageFactory.get_image('mail-thread-watch'))

        flowModeAction = viewSubMenu.addAction(
            self.main_window.QImageFactory.get_image('page-flow'),
            self._translate('PliantQTextBrowser', 'Flow text'))

        singlePageAction = viewSubMenu.addAction(
            self.main_window.QImageFactory.get_image('page-single'),
            self._translate('PliantQTextBrowser', 'Single page'))

        doublePageAction = viewSubMenu.addAction(
            self.main_window.QImageFactory.get_image('page-double'),
            self._translate('PliantQTextBrowser', 'Double page'))

        if self.parent.is_fullscreen:
            fsToggleAction = contextMenu.addAction(
                self.main_window.QImageFactory.get_image('view-fullscreen'),
                self._translate('PliantQTextBrowser', 'Exit fullscreen'))
        elif not self.main_window.settings['show_bars']:
            distraction_free_prompt = self._translate(
                'PliantQTextBrowser', 'Exit Distraction Free mode')
            dfToggleAction = contextMenu.addAction(
                self.main_window.QImageFactory.get_image('visibility'),
                distraction_free_prompt)

        if selection and selection != '':
            first_selected_word = selection.split()[0]
            elided_selection = selection
            if len(elided_selection) > 15:
                elided_selection = elided_selection[:15] + '...'

            define_string = self._translate('PliantQTextBrowser', 'Define')
            defineAction = contextMenu.addAction(
                self.main_window.QImageFactory.get_image('view-readermode'),
                f'{define_string} "{first_selected_word}"')

            search_submenu_string = self._translate('PliantQTextBrowser', 'Search for')
            searchSubMenu = contextMenu.addMenu(
                search_submenu_string + f' "{elided_selection}"')
            searchSubMenu.setIcon(self.main_window.QImageFactory.get_image('search'))

            searchAction = searchSubMenu.addAction(
                self.main_window.QImageFactory.get_image('search'),
                self._translate('PliantQTextBrowser', 'In this book'))
            searchSubMenu.addSeparator()
            searchGoogleAction = searchSubMenu.addAction(
                QtGui.QIcon(':/images/Google.png'),
                'Google')
            searchWikipediaAction = searchSubMenu.addAction(
                QtGui.QIcon(':/images/Wikipedia.png'),
                'Wikipedia')
            searchYoutubeAction = searchSubMenu.addAction(
                QtGui.QIcon(':/images/Youtube.png'),
                'Youtube')

            # Allow adding new annotation from the context menu
            if not annotation_is_present:
                annotation_string = self._translate('PliantQTextBrowser', 'Annotate')
                annotationSubmenu = contextMenu.addMenu(annotation_string)
                annotationSubmenu.setIcon(
                    self.main_window.QImageFactory.get_image('annotate'))

                saved_annotations = self.parent.main_window.settings['annotations']
                if not saved_annotations:
                    nope = annotationSubmenu.addAction('<No annotations set>')
                    nope.setEnabled(False)

                for i in saved_annotations:
                    this_action = QtWidgets.QAction(i['name'])
                    # Does not require / support a role
                    this_action.setData(i)
                    annotationActions.append(this_action)
                    annotationSubmenu.addAction(this_action)

        else:
            searchAction = contextMenu.addAction(
                self.main_window.QImageFactory.get_image('search'),
                self._translate('PliantQTextBrowser', 'Search'))
            self.common_functions.generate_combo_box_action(contextMenu)


    def closeEvent(self, *args):
        self.main_window.closeEvent()

    # def mouseMoveEvent(self, event):
    #     # Compare mouse positions
    #     # This allows to filter out scrolling
    #     # from a normal mouseEvent

    #     QtWidgets.QTextBrowser.mouseMoveEvent(self, event)
    #     if not self.mousePosition:
    #         self.mousePosition = event.pos()
    #         return

    #     current_position = event.pos()
    #     if current_position == self.mousePosition or self.parent.sideDock.isVisible():
    #         return
    #     else:
    #         self.mousePosition = event.pos()

    #         # self.viewport().setCursor(QtCore.Qt.ArrowCursor)

class Tab(QtWidgets.QWidget):
    def __init__(self, metadata, main_window, parent=None):
        super(Tab, self).__init__(parent)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.main_window = main_window
        self.metadata = metadata
        self.library = False

        self.masterLayout = QtWidgets.QHBoxLayout(self)
        self.masterLayout.setContentsMargins(0, 0, 0, 0)

        # Generate toc Model
        self.tocModel = QtGui.QStandardItemModel()
        self.tocModel.setHorizontalHeaderLabels(('Table of Contents',))
        self.generate_toc_model()

        # 设置阅读位置
        # self.generate_position()
        current_chapter = 1

        # 设置阅读页面
        self.contentView = PliantQTextBrowser(self.main_window, self)
        self.contentView.setReadOnly(True)

        # TODO
        # Change this when HTML navigation works
        self.contentView.setOpenLinks(False)

        # TODO
        # Rename the .css files to something else here and keep
        # a record of them .Currently, I'm just removing them
        # for the sake of simplicity
        relative_path_root = os.path.join(
            self.main_window.tempDir, self.metadata['hash'])
        relative_paths = []
        for i in os.walk(relative_path_root):
            for j in i[2]:
                file_extension = os.path.splitext(j)[1]
                if file_extension == '.css':
                    file_path = os.path.join(i[0], j)
                    os.remove(file_path)
            relative_paths.append(os.path.join(relative_path_root, i[0]))
        self.contentView.setSearchPaths(relative_paths)


        # All content must be set through this function
        self.set_content(current_chapter, True, False)

        self.contentView.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.contentView.setObjectName('contentView')

        self.masterLayout.addWidget(self.contentView)

        # Create tab in the central tab widget
        title = self.metadata['title']
        if len(title) > 30:
            title = title[:30] + '...'
        self.main_window.tabWidget.addTab(self, title)

    def generate_toc_model(self):
        # The toc list is:
        # 0: Level
        # 1: Title
        # 2: Chapter content / page number
        # pprint it out to get a better idea of structure

        toc = self.metadata['toc']
        parent_list = []
        for i in toc:
            item = QtGui.QStandardItem()
            item.setText(i[1])
            item.setData(i[2], QtCore.Qt.UserRole)
            item.setData(i[1], QtCore.Qt.UserRole + 1)

            current_level = i[0]
            if current_level == 1:
                self.tocModel.appendRow(item)
                parent_list.clear()
                parent_list.append(item)
            else:
                parent_list[current_level - 2].appendRow(item)
                try:
                    next_level = toc[toc.index(i) + 1][0]
                    if next_level > current_level:
                        parent_list.append(item)

                    if next_level < current_level:
                        level_difference = current_level - next_level
                        parent_list = parent_list[:-level_difference]
                except IndexError:
                    pass

        # This is needed to be able to have the toc Combobox
        # jump to the correct position in the book when it is
        # first opened
        self.main_window.bookToolBar.tocBox.setModel(self.tocModel)
        self.main_window.bookToolBar.tocTreeView.expandAll()

    def set_content(self, required_position, tocBox_readjust=False, record_position=False):
        # All content changes must come through here
        # This function will decide how to relate
        # entries in the toc to the actual content

        # Set the required page to the corresponding index
        # For images this is simply a page number
        # For text based books, this is the entire text of the chapter
        try:
            required_content = self.metadata['content'][required_position - 1]
        except IndexError:
            return  # Do not allow cycling beyond last page

        # Update the metadata dictionary to save position
        # self.metadata['position']['current_chapter'] = required_position
        # self.metadata['position']['is_read'] = False

        self.contentView.clear()
        self.contentView.setHtml(required_content)

        # Set the contentview to look the way God intended
        # self.main_window.profile_functions.format_contentView()

        # Change the index of the tocBox. This is manual and each function
        # that calls set_position must specify if it needs this adjustment
        if tocBox_readjust:
            self.set_tocBox_index(required_position, None)

            # The NavBar doesn't get declared until later
            # try:
            #     self.set_tocBox_index(
            #         required_position, self.navBar.tocComboBox)
            # except AttributeError:
            #     pass

        # self.contentView.setFocus()

    def set_tocBox_index(self, current_position=None, tocBox=None):
        # Get current position from the metadata dictionary
        # in case it isn't specified
        if not current_position:
            # current_position = self.metadata['position']['current_chapter']
            current_position = 1

        position_reference = 1
        for i in reversed(self.metadata['toc']):
            if i[2] <= current_position:
                position_reference = i[2]
                break

        # Match the position reference to the corresponding
        # index in the QTreeView / QCombobox
        try:
            matchingIndex = self.tocModel.match(
                self.tocModel.index(0, 0),
                QtCore.Qt.UserRole,
                position_reference,
                2, QtCore.Qt.MatchRecursive)[0]
        except IndexError:
            return

        # A tocBox name is specified for the context menu
        if not tocBox:
            tocBox = self.main_window.bookToolBar.tocBox

        # The following sets the QCombobox index according
        # to the index found above.
        tocBox.blockSignals(True)
        currentRootModelIndex = tocBox.rootModelIndex()
        tocBox.setRootModelIndex(matchingIndex.parent())
        tocBox.setCurrentIndex(matchingIndex.row())
        tocBox.setRootModelIndex(currentRootModelIndex)
        tocBox.blockSignals(False)
